<?php
namespace GrouppaGroup;

require_once 'Controller.php';
require_once 'MessageFromApp.php';

class ChatController extends Controller
{

    /**
     * receives a message from an application (override from controller)
     * @param  MessageFromApp    $message
     * @return MessageFromServer return message to the user
     */
    public function receiveMessage(MessageFromApp $message)
    {

        //CHECK: check access token
        if (!$this->checkAccess($message))
            return;
        //CHECK: check the "task" field in the message and send the message
        //to the appropriate function if ($message->task) {
            switch ($message->task) {
                case 'getMessages':
                    $this->getMessages($message);
                    break;
                case 'postNewMessage':
                    $this->postNewMessage($message);
                    break;
                case 'getNewMessages':
                    $this->getNewMessages($message);
                    break;
                default:
                    self::unknownTask($message);
                    break;
            }
        }
    }

    /*
    ****************** Section: functions available to call for the applications
    */
    /**
     * retrieves all messages from a certain group and sends it back to the client
     * @param  MessageFromApp $message a message with following fields in serializedArguments:
     *                                 userName, groupName
     * @return integer        number of messages retrieved
     */
    public function getMessages(MessageFromApp $message)
    {
        //CHECK: check if serializedArguments parameters have following properties:
        // userName and groupName
        if (!$message->serializedArguments || !is_a($message->serializedArguments,
            'stdClass')) {
            throw new \Exception('ChatController::getMessage error: message does not contain proper json object');
        }
        $args = $message->serializedArguments;
        if (!property_exists($args, 'userName') || !property_exists($args, 'groupName')) {
            throw new \Exception('ChatController::getMessage error: message parameters does not countain group name or
                    user name');
        }
        $userName = $args->userName;
        $groupname = $args->groupName;
        $db = Db::getInstance();
        //CHECK: retrieve all messages belonging to specified user and group
        $result = $db->sendQuery("SELECT text, user_name, time" .
            " FROM chatmessages, users, groups" .
            " WHERE chatmessages.id_group = groups.id_group" .
            " AND chatmessages.id_user = users.id_user" . " AND groups.group_name = '$groupname';");

        $newId = $db->getAutoIncrementValue('chatmessages');
        //CHECK: create MessageFromServer for containing response to client
        $messages = array();
        $n = $result->num_rows;
        for ($i = 0; $i < $n; $i++) {
            $row = $result->fetch_row();
            $messages[] = array(
                'author' => $row[1],
                'time' => $row[2],
                'text' => $row[0]);
        }

        $arguments = array(
            'retrieved' => true,
            'reason' => '',
            'newId' => $newId,
            'all_messages' => $messages);
        $serializedArguments = json_encode($arguments);
        $responseMessage = new MessageFromServer($serializedArguments, 'Chat', $message->
            messageType, $message->id);
        ApplicationTCPConnection::sendMessage($responseMessage);

        return $n;
    }

    /**
     * posts a new message on current user's active group
     * @param  MessageFromApp $message a message that has in it's serializedArguments:
     *                                 groupName, author, text, date, idFrom
     * @return boolean        true iff message was posted
     */
    public function postNewMessage(MessageFromApp $message)
    {
        //CHECK: check if serializedArguments parameters have following properties:
        // userName, groupName and messageText
        if (!$message->serializedArguments || !is_a($message->serializedArguments,
            'stdClass')) {
            throw new \Exception('ChatController::postNewMessage error: message does not contain proper json object');
        }
        $args = $message->serializedArguments;
        if (!property_exists($args, 'author') || !property_exists($args, 'text') || !
            property_exists($args, 'date') || !property_exists($args, 'groupName') || !
            property_exists($args, 'idFrom')) {
            throw new \Exception('ChatController::postNewMessage error: message parameters does not countain author or
                                  text or date or group or fromId');
        }
        $db = Db::getInstance();
        $author = $args->author;
        $text = $db->escape($args->text);
        $date = $args->date;
        $groupName = $args->groupName;
        $idFrom = $args->idFrom;

        //CHECK: try to insert the message to the table 'chatmessages'
        $result = Db::getInstance()->sendQuery("SELECT id_user , id_group" .
            " FROM users, groups" . " WHERE user_name = '$author' AND group_name='$groupName'; ");
        $row = $result->fetch_row();
        $id_user = $row[0];
        $id_group = $row[1];
        $result->free();
        $inserted = $db->sendInsertQuery("INSERT INTO chatmessages (text, id_user, id_group, time)
                        VALUES(\"$text\", $id_user, $id_group, $date)", 'chatmessages');

        //CHECK: check if inserting succeeded by calling Db::getInserted()
        //CHECK: send message with "posted" attribute set to true if inserting succeeded
        if (!$inserted) {
            $arguments = array('posted' => false, 'reason' =>
                    'ChatController::postNewMessage error: inserting chat message failed');
        } else {

            $result = $db->sendQuery("SELECT text, user_name, time" .
                " FROM chatmessages, users" . " WHERE chatmessages.id_group = $id_group" .
                " AND chatmessages.id_user = users.id_user" . " AND chatmessages.id_message >= $idFrom;");
            $newId = $db->getAutoIncrementValue('chatmessages');
            //CHECK: create MessageFromServer for containing response to client
            //CHECK: combine all messages into a serialized JSON form
            $messages = array();
            $n = $result->num_rows;
            for ($i = 0; $i < $n; $i++) {
                $row = $result->fetch_row();
                $messages[] = array(
                    'author' => $row[1],
                    'time' => $row[2],
                    'text' => $row[0]);
            }

            $arguments = array(
                'posted' => true,
                'author' => $author,
                'messageText' => $text,
                'fromId' => $idFrom,
                'newId' => $newId,
                'date' => $date,
                'groupName' => $groupName,
                'all_messages' => $messages);
        }
        ///CHECK: send error reasons if they appeared
        //Everything should be sent inside one MessageFromServer
        $serializedArguments = json_encode($arguments);
        $responseMessage = new MessageFromServer($serializedArguments, 'Chat', $message->
            messageType, $message->id);
        ApplicationTCPConnection::sendMessage($responseMessage);

    }

    /**
     * Gets new messages for specified user
     * WARNING: will not send any response if there are no new messages
     * @param  MessageFromApp $message a message with following fields in serializedArguments:
     *                                 groupName, userName, idFrom
     * @return integer        number of messages retrieved
     */
    public function getNewMessages(MessageFromApp $message)
    {
        //CHECK: check if serializedArguments parameters have following properties:
        // userName, groupName and timeFrom
        if (!$message->serializedArguments || !is_a($message->serializedArguments,
            'stdClass')) {
            throw new \Exception('ChatController::getNewMessages error: message does not contain proper json object');
        }
        $args = $message->serializedArguments;

        if (!property_exists($args, 'userName') || !property_exists($args, 'groupName') ||
            !property_exists($args, 'idFrom')) {
            throw new \Exception('ChatController::getNewMessages error: message parameters does not countain group name or user name or idFrom');
        }

        $userName = $args->userName;
        $groupName = $args->groupName;
        $idFrom = $args->idFrom;
        //CHECK: retrieve all messages belonging to specified user and group

        $db = Db::getInstance();
        $result = $db->sendQuery("SELECT text, user_name, time" .
            " FROM chatmessages, users, groups" .
            " WHERE chatmessages.id_group = groups.id_group" .
            " AND chatmessages.id_user = users.id_user" . " AND groups.group_name = '$groupName'" .
            " AND chatmessages.id_message >= $idFrom;");
        //CHECK: create MessageFromServer for containing response to client
        //CHECK: combine all messages into a serialized JSON form
        $messages = array();
        $n = $result->num_rows;
        if ($n == 0)
            return 0;
        for ($i = 0; $i < $n; $i++) {
            $row = $result->fetch_row();
            $messages[] = array(
                'author' => $row[1],
                'time' => $row[2],
                'text' => $row[0]);
        }

        $newId = $db->getAutoIncrementValue('chatmessages');
        $arguments = array(
            'retrieved' => true,
            'error_reason' => '',
            'fromId' => $idFrom,
            'newId' => $newId,
            'all_messages' => $messages,
            'number' => $n);
        $serializedArguments = json_encode($arguments);
        //CHECK: send all messages to client , all messages in a table in json form
        //should be inside serialized
        $responseMessage = new MessageFromServer($serializedArguments, 'Chat', $message->
            messageType, $message->id);
        $responseMessage->toController='ChatView';
        ApplicationTCPConnection::sendMessage($responseMessage);

        return $n;

    }

}
